/*     */ package com.zimbra.cs.dav.caldav;
/*     */ 
/*     */ import com.google.common.base.Strings;
/*     */ import com.google.common.collect.ImmutableMap;
/*     */ import com.google.common.collect.Lists;
/*     */ import com.zimbra.common.calendar.ParsedDateTime;
/*     */ import com.zimbra.common.calendar.ZCalendar.ICalTok;
/*     */ import com.zimbra.common.calendar.ZCalendar.ZVCalendar;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Account;
/*     */ import com.zimbra.cs.dav.DavContext;
/*     */ import com.zimbra.cs.dav.resource.DavResource;
/*     */ import com.zimbra.cs.mailbox.CalendarItem;
/*     */ import com.zimbra.cs.mailbox.CalendarItem.Instance;
/*     */ import com.zimbra.cs.mailbox.CalendarItem.ReplyInfo;
/*     */ import com.zimbra.cs.mailbox.MailSender;
/*     */ import com.zimbra.cs.mailbox.MailServiceException;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.Mailbox.SetCalendarItemData;
/*     */ import com.zimbra.cs.mailbox.MailboxManager;
/*     */ import com.zimbra.cs.mailbox.calendar.CalendarMailSender;
/*     */ import com.zimbra.cs.mailbox.calendar.FriendlyCalendaringDescription;
/*     */ import com.zimbra.cs.mailbox.calendar.Invite;
/*     */ import com.zimbra.cs.mailbox.calendar.OrganizerInviteChanges;
/*     */ import com.zimbra.cs.mailbox.calendar.RecurId;
/*     */ import com.zimbra.cs.mailbox.calendar.ZAttendee;
/*     */ import com.zimbra.cs.mailbox.calendar.ZOrganizer;
/*     */ import com.zimbra.cs.util.AccountUtil;
/*     */ import java.util.Iterator;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import javax.mail.Address;
/*     */ import javax.mail.internet.MimeMessage;
/*     */ import javax.servlet.http.HttpServletRequest;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public abstract class AutoScheduler
/*     */ {
/*     */   public static final String CANCEL_PREFIX = "Cancel: ";
/*     */   protected final Mailbox userMailbox;
/*     */   protected final Account calendarAccount;
/*     */   protected final Invite[] origInvites;
/*     */   protected final Mailbox.SetCalendarItemData scidDefault;
/*     */   protected final Mailbox.SetCalendarItemData[] scidExceptions;
/*  64 */   protected final List<Invite> newInvites = Lists.newArrayList();
/*     */   
/*     */   protected final int calendarMailItemId;
/*     */   
/*     */   protected final int flags;
/*     */   
/*     */   protected final String[] tags;
/*     */   
/*     */   protected final List<CalendarItem.ReplyInfo> replies;
/*     */   
/*     */   protected final DavContext ctxt;
/*     */   
/*     */   protected final Address from;
/*     */   
/*     */   protected final Address sender;
/*     */   
/*     */   protected final ZOrganizer organizer;
/*     */   
/*     */ 
/*     */   protected AutoScheduler(Mailbox userMailbox, Mailbox calendarMailbox, Invite[] origInvites, int calendarMailItemId, int flags, String[] tags, Mailbox.SetCalendarItemData scidDefault, Mailbox.SetCalendarItemData[] scidExceptions, List<CalendarItem.ReplyInfo> replies, DavContext ctxt)
/*     */     throws ServiceException
/*     */   {
/*  86 */     this.userMailbox = userMailbox;
/*  87 */     if (calendarMailbox == null) {
/*  88 */       this.calendarAccount = null;
/*  89 */       this.from = null;
/*  90 */       this.sender = null;
/*     */     } else {
/*  92 */       this.calendarAccount = calendarMailbox.getAccount();
/*  93 */       this.from = AccountUtil.getFriendlyEmailAddress(this.calendarAccount);
/*     */       
/*  95 */       if (ctxt.getAuthAccount().equals(this.calendarAccount)) {
/*  96 */         this.sender = null;
/*     */       } else {
/*  98 */         this.sender = AccountUtil.getFriendlyEmailAddress(ctxt.getAuthAccount());
/*     */       }
/*     */     }
/* 101 */     this.origInvites = (origInvites == null ? new Invite[0] : origInvites);
/* 102 */     this.calendarMailItemId = calendarMailItemId;
/* 103 */     this.flags = flags;
/* 104 */     this.tags = tags;
/* 105 */     this.scidDefault = scidDefault;
/* 106 */     this.scidExceptions = scidExceptions;
/* 107 */     this.replies = replies;
/* 108 */     if (scidDefault != null) {
/* 109 */       this.newInvites.add(scidDefault.invite);
/* 110 */       if (scidExceptions != null) {
/* 111 */         for (Mailbox.SetCalendarItemData scid : scidExceptions) {
/* 112 */           this.newInvites.add(scid.invite);
/*     */         }
/*     */       }
/* 115 */       this.organizer = scidDefault.invite.getOrganizer();
/* 116 */     } else if (origInvites.length >= 1) {
/* 117 */       this.organizer = origInvites[0].getOrganizer();
/*     */     } else {
/* 119 */       this.organizer = null;
/*     */     }
/* 121 */     this.ctxt = ctxt;
/*     */   }
/*     */   
/*     */   private static boolean isEmpty(Invite[] invites) {
/* 125 */     return (invites == null) || (invites.length <= 0);
/*     */   }
/*     */   
/*     */   public abstract CalendarItem doSchedulingActions() throws ServiceException;
/*     */   
/*     */   private static void addSchedulingMsg(List<AutoScheduleMsg> msgs, AutoScheduleMsg msg) {
/* 131 */     if (msg == null) {
/* 132 */       return;
/*     */     }
/* 134 */     if (ZimbraLog.dav.isDebugEnabled()) {
/* 135 */       Invite inv = msg.calendarInvite;
/* 136 */       if (inv != null) {
/* 137 */         String recurId = inv.getRecurId() == null ? "NONE" : inv.getRecurId().toString();
/* 138 */         ZimbraLog.dav.debug("Will schedule msg with method %s for UID %s Recurrence ID %s\n%s", new Object[] { msg.msgMethod, inv.getUid(), recurId, ZimbraLog.getStackTrace(5) });
/*     */       }
/*     */     }
/*     */     
/* 142 */     msgs.add(msg);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   public static AutoScheduler getAutoScheduler(Mailbox userMailbox, Mailbox calendarMailbox, Invite[] origInvites, int calendarMailItemId, DavContext context)
/*     */   {
/* 150 */     return getAutoScheduler(userMailbox, calendarMailbox, origInvites, calendarMailItemId, 0, null, null, null, null, context);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   public static AutoScheduler getAutoScheduler(Mailbox userMailbox, Mailbox calendarMailbox, Invite[] origInvites, int calendarMailItemId, int flags, String[] tags, Mailbox.SetCalendarItemData scidDefault, Mailbox.SetCalendarItemData[] scidExceptions, List<CalendarItem.ReplyInfo> replies, DavContext context)
/*     */   {
/* 157 */     if (!DavResource.isCalendarAutoSchedulingEnabled()) {
/* 158 */       return null;
/*     */     }
/* 160 */     if (calendarMailbox == null) {
/* 161 */       return null;
/*     */     }
/* 163 */     ZOrganizer organizer = null;
/* 164 */     Account organizerAcct = null;
/*     */     try {
/* 166 */       if ((scidDefault == null) || (scidDefault.invite == null)) {
/* 167 */         if (isEmpty(origInvites)) {
/* 168 */           return null;
/*     */         }
/* 170 */         organizer = origInvites[0].getOrganizer();
/* 171 */         organizerAcct = origInvites[0].getOrganizerAccount();
/*     */       } else {
/* 173 */         organizer = scidDefault.invite.getOrganizer();
/* 174 */         organizerAcct = scidDefault.invite.getOrganizerAccount();
/*     */       }
/* 176 */       if (organizer == null) {
/* 177 */         return null;
/*     */       }
/*     */       
/* 180 */       if (calendarMailbox.getAccount().equals(organizerAcct)) {
/* 181 */         return new OrganizerAutoScheduler(userMailbox, calendarMailbox, origInvites, calendarMailItemId, flags, tags, scidDefault, scidExceptions, replies, context);
/*     */       }
/*     */       
/* 184 */       return new AttendeeAutoScheduler(userMailbox, calendarMailbox, origInvites, calendarMailItemId, flags, tags, scidDefault, scidExceptions, replies, context);
/*     */     }
/*     */     catch (ServiceException e)
/*     */     {
/* 188 */       ZimbraLog.dav.debug("Hit this whilst getting AutoScheduler", e);
/*     */     }
/* 190 */     return null;
/*     */   }
/*     */   
/*     */   protected CalendarItem persistToCalendar() throws ServiceException {
/* 194 */     if (null == this.scidDefault) {
/* 195 */       return null;
/*     */     }
/* 197 */     return this.userMailbox.setCalendarItem(this.ctxt.getOperationContext(), this.calendarMailItemId, this.flags, this.tags, this.scidDefault, this.scidExceptions, this.replies, 0L);
/*     */   }
/*     */   
/*     */   protected CalendarItem processSchedulingMessages(List<AutoScheduleMsg> msgs) throws ServiceException
/*     */   {
/* 202 */     for (AutoScheduleMsg msg : msgs) {
/* 203 */       msg.updateCalendarInfo();
/*     */     }
/* 205 */     CalendarItem newCalItem = persistToCalendar();
/*     */     
/* 207 */     for (AutoScheduleMsg msg : msgs) {
/* 208 */       msg.sendSchedulingMsg();
/*     */     }
/* 210 */     return newCalItem;
/*     */   }
/*     */   
/*     */   protected class AutoScheduleMsg {
/*     */     Invite calendarInvite;
/*     */     ZCalendar.ICalTok msgMethod;
/*     */     List<Address> recipients;
/*     */     String subject;
/*     */     
/* 219 */     protected AutoScheduleMsg(ZCalendar.ICalTok calendarInvite, List<Address> msgMethod, String recipients) { this.calendarInvite = calendarInvite;
/* 220 */       this.msgMethod = msgMethod;
/* 221 */       this.recipients = recipients;
/* 222 */       this.subject = subject;
/*     */     }
/*     */     
/*     */     public void updateCalendarInfo() {
/* 226 */       if ((this.recipients == null) || (this.recipients.isEmpty())) {
/* 227 */         return;
/*     */       }
/* 229 */       if (ZCalendar.ICalTok.REQUEST.equals(this.msgMethod))
/*     */       {
/* 231 */         this.calendarInvite.setRsvp(true);
/* 232 */         this.calendarInvite.setMethod(this.msgMethod.toString());
/* 233 */         for (ZAttendee attendee : this.calendarInvite.getAttendees()) {
/* 234 */           if ((!attendee.hasRsvp()) || (!attendee.getRsvp().booleanValue())) {
/* 235 */             for (Address recip : this.recipients) {
/*     */               try {
/* 237 */                 attendee.getFriendlyAddress();
/*     */               } catch (ServiceException e) {
/* 239 */                 ZimbraLog.dav.debug("Problem getting friendly address for attendee %s", attendee, e);
/*     */               }
/* 241 */               if (attendee.addressMatches(recip)) {
/* 242 */                 attendee.setRsvp(Boolean.valueOf(true));
/*     */               }
/*     */             }
/*     */           }
/* 246 */           if (Strings.isNullOrEmpty(attendee.getRole())) {
/* 247 */             attendee.setRole("REQ");
/*     */           }
/* 249 */           if (Strings.isNullOrEmpty(attendee.getPartStat())) {
/* 250 */             attendee.setPartStat("NE");
/*     */           }
/*     */         }
/*     */       }
/*     */     }
/*     */     
/*     */     public void sendSchedulingMsg() {
/* 257 */       if ((this.recipients == null) || (this.recipients.isEmpty())) {
/* 258 */         ZimbraLog.dav.trace("Not generating a scheduling message for UID=%s start=%s - no recipients", new Object[] { this.calendarInvite.getUid(), this.calendarInvite.getStartTime() });
/*     */         
/* 260 */         return;
/*     */       }
/*     */       try {
/* 263 */         Invite msgInvite = this.calendarInvite.newCopy();
/* 264 */         msgInvite.setMethod(this.msgMethod.toString());
/* 265 */         if (ZCalendar.ICalTok.REQUEST.equals(this.msgMethod)) {
/* 266 */           for (ZAttendee attendee : msgInvite.getAttendees()) {
/* 267 */             attendee.setRsvp(Boolean.valueOf(true));
/* 268 */             attendee.setPartStat("NE");
/*     */           }
/* 270 */         } else if (ZCalendar.ICalTok.CANCEL.equals(this.msgMethod)) {
/* 271 */           msgInvite.setStatus("CANC");
/* 272 */           msgInvite.setTransparency("T");
/* 273 */           for (ZAttendee attendee : msgInvite.getAttendees()) {
/* 274 */             attendee.setRsvp(null);
/* 275 */             attendee.setPartStat("NE");
/*     */           }
/* 277 */         } else if (ZCalendar.ICalTok.REPLY.equals(this.msgMethod))
/*     */         {
/* 279 */           List<ZAttendee> attendees = msgInvite.getAttendees();
/* 280 */           Iterator<ZAttendee> attendeeIter = attendees.iterator();
/* 281 */           while (attendeeIter.hasNext()) {
/* 282 */             ZAttendee attendee = (ZAttendee)attendeeIter.next();
/* 283 */             if (!attendee.addressMatches(AutoScheduler.this.from)) {
/* 284 */               attendeeIter.remove();
/*     */             }
/*     */           }
/*     */         }
/* 288 */         FriendlyCalendaringDescription friendlyDesc = new FriendlyCalendaringDescription(msgInvite, AutoScheduler.this.ctxt.getAuthAccount());
/*     */         
/* 290 */         String desc = friendlyDesc.getAsPlainText();
/* 291 */         String descHtml = friendlyDesc.getAsHtml();
/* 292 */         String uid = msgInvite.getUid();
/* 293 */         ZCalendar.ZVCalendar cal = msgInvite.newToICalendar(true);
/* 294 */         Mailbox mbox = MailboxManager.getInstance().getMailboxByAccount(AutoScheduler.this.ctxt.getAuthAccount());
/* 295 */         MimeMessage mm = CalendarMailSender.createCalendarMessage(AutoScheduler.this.ctxt.getAuthAccount(), AutoScheduler.this.from, AutoScheduler.this.sender, this.recipients, this.subject, desc, descHtml, uid, cal, msgInvite.getIcalendarAttaches(), true);
/*     */         
/* 297 */         mbox.getMailSender().setSendPartial(true).sendMimeMessage(AutoScheduler.this.ctxt.getOperationContext(), mbox, Boolean.valueOf(true), mm, null, null, null, null, false);
/*     */       }
/*     */       catch (ServiceException e) {
/* 300 */         ZimbraLog.dav.info("Exception thrown when creating auto scheduling message", e);
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */   public static class OrganizerAutoScheduler
/*     */     extends AutoScheduler
/*     */   {
/*     */     protected OrganizerAutoScheduler(Mailbox userMailbox, Mailbox calendarMailbox, Invite[] origInvites, int calendarMailItemId, int flags, String[] tags, Mailbox.SetCalendarItemData scidDefault, Mailbox.SetCalendarItemData[] scidExceptions, List<CalendarItem.ReplyInfo> replies, DavContext ctxt)
/*     */       throws ServiceException
/*     */     {
/* 311 */       super(calendarMailbox, origInvites, calendarMailItemId, flags, tags, scidDefault, scidExceptions, replies, ctxt);
/*     */     }
/*     */     
/*     */     public CalendarItem doSchedulingActions()
/*     */       throws ServiceException
/*     */     {
/* 317 */       if (AutoScheduler.isEmpty(this.origInvites)) {
/* 318 */         return doSchedulingActionsForNewCreate();
/*     */       }
/* 320 */       return doSchedulingActionsForUpdate();
/*     */     }
/*     */     
/*     */     private CalendarItem doSchedulingActionsForNewCreate() throws ServiceException
/*     */     {
/* 325 */       List<AutoScheduler.AutoScheduleMsg> msgs = Lists.newArrayList();
/*     */       
/* 327 */       Invite seriesOrSingletonInvite = Invite.matchingInvite(this.newInvites, null);
/* 328 */       List<Address> seriesAttendees = Lists.newArrayListWithCapacity(0);
/* 329 */       if (seriesOrSingletonInvite != null) {
/* 330 */         seriesAttendees = getRecipientsForAttendees(seriesOrSingletonInvite);
/* 331 */         if (!seriesAttendees.isEmpty()) {
/* 332 */           AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, seriesOrSingletonInvite, ZCalendar.ICalTok.REQUEST, seriesAttendees, seriesOrSingletonInvite.getName()));
/*     */         }
/*     */       }
/*     */       
/* 336 */       for (Invite inv : this.newInvites) {
/* 337 */         if (inv != seriesOrSingletonInvite) {
/* 338 */           List<Address> exceptAttendees = getRecipientsForAttendees(inv);
/* 339 */           AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, inv, ZCalendar.ICalTok.REQUEST, exceptAttendees, inv.getName()));
/*     */           
/*     */ 
/* 342 */           seriesAttendees.removeAll(exceptAttendees);
/* 343 */           if (!seriesAttendees.isEmpty()) {
/* 344 */             AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, inv, ZCalendar.ICalTok.CANCEL, seriesAttendees, "Cancel: " + inv.getName()));
/*     */           }
/*     */         }
/*     */       }
/*     */       
/* 349 */       return processSchedulingMessages(msgs);
/*     */     }
/*     */     
/*     */     private CalendarItem doSchedulingActionsForUpdate() throws ServiceException {
/* 353 */       List<AutoScheduler.AutoScheduleMsg> msgs = Lists.newArrayList();
/*     */       
/* 355 */       Invite oldSeriesOrSingletonInvite = Invite.matchingInvite(this.origInvites, null);
/*     */       
/* 357 */       Invite newInvite = Invite.matchingInvite(this.newInvites, oldSeriesOrSingletonInvite == null ? null : oldSeriesOrSingletonInvite.getRecurId());
/*     */       
/* 359 */       OrganizerInviteChanges changeInfo = new OrganizerInviteChanges(oldSeriesOrSingletonInvite, newInvite);
/* 360 */       if (changeInfo.inviteCanceled()) {
/* 361 */         AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, oldSeriesOrSingletonInvite, ZCalendar.ICalTok.CANCEL, getRecipientsForAttendees(oldSeriesOrSingletonInvite), "Cancel: " + changeInfo.getSubject()));
/*     */       }
/*     */       else
/*     */       {
/* 365 */         if (changeInfo.isChanged()) {
/* 366 */           List<Address> recips = changeInfo.isReplyInvalidatingChange() ? getRecipientsForAttendees(newInvite) : getRecipientsForAttendees(changeInfo.getAttendeesOnlyInNew());
/*     */           
/*     */ 
/* 369 */           if (!recips.isEmpty()) {
/* 370 */             bumpSequenceNumberIfNecessary(oldSeriesOrSingletonInvite, newInvite);
/* 371 */             AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, newInvite, ZCalendar.ICalTok.REQUEST, recips, changeInfo.getSubject()));
/*     */           }
/*     */         }
/*     */         
/* 375 */         if (oldSeriesOrSingletonInvite != null) {
/* 376 */           List<Address> uninvited = getRecipientsForAttendees(changeInfo.getAttendeesOnlyInOld());
/* 377 */           if (!uninvited.isEmpty()) {
/* 378 */             AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, oldSeriesOrSingletonInvite, ZCalendar.ICalTok.CANCEL, uninvited, "Cancel: " + oldSeriesOrSingletonInvite.getName()));
/*     */           }
/*     */         }
/*     */         
/*     */ 
/*     */ 
/*     */ 
/* 385 */         addCancelsForNewExdates(msgs, changeInfo);
/*     */       }
/*     */       
/* 388 */       for (Invite inv : this.origInvites) {
/* 389 */         if (inv != oldSeriesOrSingletonInvite)
/*     */         {
/*     */ 
/* 392 */           newInvite = Invite.matchingInvite(this.newInvites, inv.getRecurId());
/* 393 */           if (newInvite == null) {
/* 394 */             AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, inv, ZCalendar.ICalTok.CANCEL, getRecipientsForAttendees(inv), "Cancel: " + inv.getName()));
/*     */           }
/* 396 */           else if (newInvite.isNewerVersion(inv)) {
/* 397 */             changeInfo = new OrganizerInviteChanges(inv, newInvite);
/* 398 */             if (changeInfo.isChanged()) {
/* 399 */               List<Address> recips = changeInfo.isReplyInvalidatingChange() ? getRecipientsForAttendees(newInvite) : getRecipientsForAttendees(changeInfo.getAttendeesOnlyInNew());
/*     */               
/*     */ 
/* 402 */               if (!recips.isEmpty()) {
/* 403 */                 bumpSequenceNumberIfNecessary(inv, newInvite);
/* 404 */                 AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, newInvite, ZCalendar.ICalTok.REQUEST, recips, changeInfo.getSubject()));
/*     */               }
/*     */             }
/*     */             
/* 408 */             List<Address> uninvited = getRecipientsForAttendees(changeInfo.getAttendeesOnlyInOld());
/* 409 */             if (!uninvited.isEmpty()) {
/* 410 */               AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, inv, ZCalendar.ICalTok.CANCEL, uninvited, "Cancel: " + inv.getName()));
/*     */             }
/*     */           }
/*     */         }
/*     */       }
/*     */       
/* 416 */       Invite newSeriesOrSingletonInvite = Invite.matchingInvite(this.newInvites, null);
/*     */       
/* 418 */       for (Invite inv : this.newInvites) {
/* 419 */         Invite origInvite = Invite.matchingInvite(this.origInvites, inv.getRecurId());
/* 420 */         if (origInvite == null)
/*     */         {
/*     */ 
/* 423 */           List<Address> recips = getRecipientsForAttendees(inv);
/* 424 */           AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, inv, ZCalendar.ICalTok.REQUEST, recips, inv.getName()));
/* 425 */           List<Address> cancelRecips = getRecipientsForAttendees(newSeriesOrSingletonInvite);
/*     */           
/* 427 */           for (Address addr : recips) {
/* 428 */             Iterator<Address> recipsIter = cancelRecips.iterator();
/* 429 */             while (recipsIter.hasNext()) {
/* 430 */               Address recip = (Address)recipsIter.next();
/* 431 */               if (addr.equals(recip)) {
/* 432 */                 recipsIter.remove();
/*     */               }
/*     */             }
/*     */           }
/* 436 */           if (!cancelRecips.isEmpty()) {
/* 437 */             AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, inv, ZCalendar.ICalTok.CANCEL, cancelRecips, "Cancel: " + inv.getName()));
/*     */           }
/*     */         }
/*     */       }
/* 441 */       return processSchedulingMessages(msgs);
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */     private void bumpSequenceNumberIfNecessary(Invite oldInvite, Invite newInvite)
/*     */     {
/* 456 */       if ((oldInvite == null) || (newInvite == null)) {
/* 457 */         return;
/*     */       }
/* 459 */       int newSeqNum = newInvite.getSeqNo();
/* 460 */       if (newSeqNum == oldInvite.getSeqNo()) {
/* 461 */         ZimbraLog.dav.debug("Update has same SEQUENCE %d as previous rev. Incrementing on behalf of client", new Object[] { Integer.valueOf(newSeqNum) });
/*     */         
/* 463 */         newInvite.setSeqNo(newSeqNum + 1);
/*     */       }
/*     */     }
/*     */     
/*     */     private void addCancelsForNewExdates(List<AutoScheduler.AutoScheduleMsg> msgs, OrganizerInviteChanges changeInfo)
/*     */     {
/* 469 */       for (CalendarItem.Instance exdateOnlyInNew : changeInfo.getExdatesOnlyInNew()) {
/* 470 */         Invite cancel = changeInfo.newInvite.newCopy();
/* 471 */         cancel.setRecurrence(null);
/* 472 */         ParsedDateTime start = ParsedDateTime.fromUTCTime(exdateOnlyInNew.getStart());
/* 473 */         cancel.setDtStart(start);
/* 474 */         cancel.setRecurId(new RecurId(start, RecurId.RANGE_NONE));
/* 475 */         cancel.setDtEnd(ParsedDateTime.fromUTCTime(exdateOnlyInNew.getEnd()));
/* 476 */         AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, cancel, ZCalendar.ICalTok.CANCEL, getRecipientsForAttendees(cancel), "Cancel: " + cancel.getName()));
/*     */       }
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */     public List<Address> getRecipientsForAttendees(List<ZAttendee> attendees)
/*     */     {
/* 485 */       if ((attendees == null) || (attendees.isEmpty())) {
/* 486 */         return Lists.newArrayListWithCapacity(0);
/*     */       }
/* 488 */       List<Address> recipients = Lists.newArrayListWithCapacity(attendees.size());
/* 489 */       for (ZAttendee attendee : attendees) {
/*     */         try {
/* 491 */           if (AccountUtil.addressMatchesAccount(this.calendarAccount, attendee.getAddress())) {
/*     */             continue;
/*     */           }
/*     */         }
/*     */         catch (ServiceException se) {}
/*     */         try {
/* 497 */           recipients.add(attendee.getFriendlyAddress());
/*     */         } catch (MailServiceException mse) {
/* 499 */           ZimbraLog.dav.info("Problem adding attendee %s to recipient list - ignoring", attendee, mse);
/*     */         }
/*     */       }
/* 502 */       return recipients;
/*     */     }
/*     */     
/*     */     public List<Address> getRecipientsForAttendees(Invite inv) {
/* 506 */       if (inv == null) {
/* 507 */         return Lists.newArrayListWithCapacity(0);
/*     */       }
/* 509 */       return getRecipientsForAttendees(inv.getAttendees());
/*     */     }
/*     */   }
/*     */   
/*     */   public static class AttendeeAutoScheduler extends AutoScheduler {
/* 514 */     private boolean scheduleReplyWanted = true;
/*     */     
/*     */     protected AttendeeAutoScheduler(Mailbox userMailbox, Mailbox calendarMailbox, Invite[] origInvites, int calendarMailItemId, int flags, String[] tags, Mailbox.SetCalendarItemData scidDefault, Mailbox.SetCalendarItemData[] scidExceptions, List<CalendarItem.ReplyInfo> replies, DavContext ctxt)
/*     */       throws ServiceException
/*     */     {
/* 519 */       super(calendarMailbox, origInvites, calendarMailItemId, flags, tags, scidDefault, scidExceptions, replies, ctxt);
/*     */       
/* 521 */       HttpServletRequest httpRequest = ctxt.getRequest();
/* 522 */       if ((httpRequest != null) && ("DELETE".equalsIgnoreCase(httpRequest.getMethod()))) {
/* 523 */         String hdrScheduleReply = httpRequest.getHeader("Schedule-Reply");
/* 524 */         this.scheduleReplyWanted = ((hdrScheduleReply == null) || (!"F".equals(hdrScheduleReply)));
/*     */       }
/*     */     }
/*     */     
/*     */     public CalendarItem doSchedulingActions() throws ServiceException
/*     */     {
/* 530 */       List<AutoScheduler.AutoScheduleMsg> msgs = Lists.newArrayList();
/* 531 */       if (this.organizer == null) {
/* 532 */         return persistToCalendar();
/*     */       }
/* 534 */       if (!this.scheduleReplyWanted) {
/* 535 */         ZimbraLog.dav.debug("Skipping scheduling actions because HTTP header '%s=F'", new Object[] { "Schedule-Reply" });
/*     */         
/* 537 */         return persistToCalendar();
/*     */       }
/*     */       Address organizerAddress;
/*     */       try {
/* 541 */         organizerAddress = this.organizer.getFriendlyAddress();
/*     */       } catch (MailServiceException mse) {
/* 543 */         ZimbraLog.dav.info("Problem creating Address for organizer %s - ignoring", this.organizer, mse);
/* 544 */         return persistToCalendar();
/*     */       }
/* 546 */       for (Invite inv : this.newInvites) {
/* 547 */         ZAttendee attendee = getMatchingAttendee(inv.getAttendees());
/* 548 */         if (attendee != null)
/*     */         {
/*     */ 
/* 551 */           String partStat = attendee.getPartStat();
/* 552 */           if ((partStat != null) && (REPLY_PARTSTAT_SUBJECT_MAP.containsKey(partStat)))
/*     */           {
/*     */ 
/* 555 */             if (!AutoScheduler.isEmpty(this.origInvites)) {
/* 556 */               Invite origInvite = Invite.matchingInvite(this.origInvites, inv.getRecurId());
/* 557 */               if (origInvite != null) {
/* 558 */                 ZAttendee origAttendee = getMatchingAttendee(origInvite.getAttendees());
/* 559 */                 if ((origAttendee != null) && 
/* 560 */                   (partStat.equals(origAttendee.getPartStat()))) {
/*     */                   continue;
/*     */                 }
/*     */               }
/*     */             }
/*     */             
/* 566 */             StringBuilder subject = new StringBuilder();
/* 567 */             subject.append((String)REPLY_PARTSTAT_SUBJECT_MAP.get(partStat)).append(inv.getName());
/* 568 */             AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, inv, ZCalendar.ICalTok.REPLY, Lists.newArrayList(new Address[] { organizerAddress }), subject.toString()));
/*     */           }
/*     */         }
/*     */       }
/* 572 */       for (Invite inv : this.origInvites) {
/* 573 */         Invite newInvite = Invite.matchingInvite(this.newInvites, inv.getRecurId());
/* 574 */         if (newInvite == null) {
/* 575 */           Invite decline = inv.newCopy();
/* 576 */           List<ZAttendee> attendees = decline.getAttendees();
/* 577 */           Iterator<ZAttendee> attendeeIter = attendees.iterator();
/* 578 */           while (attendeeIter.hasNext()) {
/* 579 */             ZAttendee attendee = (ZAttendee)attendeeIter.next();
/* 580 */             if (attendee.addressMatches(this.from)) {
/* 581 */               attendee.setPartStat("DE");
/*     */             } else {
/* 583 */               attendeeIter.remove();
/*     */             }
/*     */           }
/* 586 */           String subject = (String)REPLY_PARTSTAT_SUBJECT_MAP.get("DE") + decline.getName();
/*     */           
/*     */ 
/* 589 */           decline.setName(subject);
/* 590 */           AutoScheduler.addSchedulingMsg(msgs, new AutoScheduler.AutoScheduleMsg(this, decline, ZCalendar.ICalTok.REPLY, Lists.newArrayList(new Address[] { organizerAddress }), subject));
/*     */         }
/*     */       }
/*     */       
/* 594 */       return processSchedulingMessages(msgs);
/*     */     }
/*     */     
/*     */     private ZAttendee getMatchingAttendee(List<ZAttendee> attendees) {
/* 598 */       if ((attendees == null) || (attendees.isEmpty())) {
/* 599 */         return null;
/*     */       }
/* 601 */       for (ZAttendee attendee : attendees) {
/*     */         try {
/* 603 */           if (AccountUtil.addressMatchesAccount(this.calendarAccount, attendee.getAddress())) {
/* 604 */             return attendee;
/*     */           }
/*     */         } catch (ServiceException e) {
/* 607 */           ZimbraLog.dav.debug("problem matching attendee '%s' to account '%s'", attendee, this.calendarAccount.getName(), e);
/*     */         }
/*     */       }
/*     */       
/* 611 */       return null;
/*     */     }
/*     */     
/* 614 */     static final Map<String, String> REPLY_PARTSTAT_SUBJECT_MAP = ImmutableMap.of("AC", "Accept: ", "TE", "Tentative: ", "DE", "Decline: ");
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/dav/caldav/AutoScheduler.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */